package com.brainydroid.datasend;

import java.util.ArrayList;
import java.util.Enumeration;
import java.util.List;

import com.brainydroid.datasend.MainActivity;
import com.google.gson.Gson;

import android.app.Activity;
import android.content.SharedPreferences;
import android.os.AsyncTask;
import android.os.Bundle;
import android.preference.PreferenceManager;
import android.util.Log;
import android.view.View;
import android.view.Window;
import android.widget.ArrayAdapter;
import android.widget.EditText;
import android.widget.Spinner;
import android.widget.TextView;
import android.widget.Toast;


public class MainActivity extends Activity {

    private static String TAG = MainActivity.class.getSimpleName();
    
    private static String BS_DEFAULT_EXP_APP_ID = "app1";
    private static String BS_DEFAULT_SERVER_NAME = "http://mehho.net:5000/";
    
    private TextView maiIdText;
    private TextView publicKeyText;
    private TextView privateKeyText;
    private EditText serverNameEdit;
    private EditText appIdEdit;
    private Spinner curveNameSpinner;

    private CryptoStore cryptostore;
    private Gson gson;
    
    @Override
    public void onCreate(Bundle savedInstanceState) {
        requestWindowFeature(Window.FEATURE_INDETERMINATE_PROGRESS);
        
        super.onCreate(savedInstanceState);
        setContentView(R.layout.main);

        setProgressBarIndeterminateVisibility(false);
        
        cryptostore = CryptoStore.getInstance(BS_DEFAULT_SERVER_NAME, this.getCacheDir());
        gson = new Gson();

        maiIdText = (TextView) findViewById(R.id.maiIdText);
        publicKeyText = (TextView) findViewById(R.id.publicKeyText);
        privateKeyText = (TextView) findViewById(R.id.privateKeyText);
        serverNameEdit = (EditText) findViewById(R.id.serverNameEdit);
        appIdEdit = (EditText) findViewById(R.id.appIdEdit);
        curveNameSpinner = (Spinner) findViewById(R.id.curveNameSpinner);
        
        List<String> curveNames = new ArrayList<String>();
        for (Enumeration<String> e = cryptostore.getAvailableCurveNames(); e.hasMoreElements();) {
        	curveNames.add(e.nextElement());
        }
        ArrayAdapter<String> curveNamesAdapter = new ArrayAdapter<String>(this,
        		android.R.layout.simple_spinner_dropdown_item, curveNames);
        curveNamesAdapter.setDropDownViewResource(android.R.layout.simple_spinner_dropdown_item);
        curveNameSpinner.setAdapter(curveNamesAdapter);
        curveNameSpinner.setOnItemSelectedListener(new OnCurveNameItemSelectedListener(cryptostore));
        
        serverNameEdit.setText(BS_DEFAULT_SERVER_NAME);
        appIdEdit.setText(BS_DEFAULT_EXP_APP_ID);
        
        if (cryptostore.hasStoredKeyPairAndMaiId()) {
        	updateKeyPairAndMaiIdText();
        }
    }
    
    private void updateKeyPairAndMaiIdText() {
    	maiIdText.setText(cryptostore.getMaiId());
    	publicKeyText.setText(cryptostore.getArmoredPublicKeyString());
    	privateKeyText.setText(cryptostore.getPrivateKeyString());
    }
    
    private void clearKeyPairAndMaiIdText() {
    	maiIdText.setText("");
        publicKeyText.setText("");
        privateKeyText.setText("");
    }
    
    public void onClick_generateKeysButton(View view) {
        SharedPreferences prefs = PreferenceManager
                .getDefaultSharedPreferences(this);
    	generateKeys(prefs);
    }
    
    private void generateKeys(SharedPreferences prefs) {
    	
    	updateServerName();
    	
        new AsyncTask<Void, Void, Boolean>() {

        	Exception error;
        	
            @Override
            protected void onPreExecute() {
                Toast.makeText(MainActivity.this, "Generating ECDSA keys...",
                        Toast.LENGTH_SHORT).show();
                setProgressBarIndeterminateVisibility(true);
            }
            
            @Override
            protected Boolean doInBackground(Void... arg0) {
			    try {
					return cryptostore.generateAndStoreKeyPairAndMaiId();
				} catch (Exception e) {
					Log.e(TAG, "Error generating keys or getting an mai_id: " + e.getMessage(), error);
					error = e;
					
					return false;
				}
            }

            @Override
            protected void onPostExecute(Boolean result) {
                setProgressBarIndeterminateVisibility(false);

                if (result) {
                	updateKeyPairAndMaiIdText();
                    Toast.makeText(MainActivity.this,
                            "Successfully generated and saved keys and an mai_id.",
                            Toast.LENGTH_SHORT).show();
                } else {
                    Toast.makeText(MainActivity.this,
                    		error == null ? "Error generating keys or getting an mai_id" : error
                                    .getMessage(), Toast.LENGTH_LONG).show();
                }
            }
        }.execute();
    }

    public void onClick_clearButton(View view) {
        SharedPreferences prefs = PreferenceManager
                .getDefaultSharedPreferences(this);
        clear(prefs);
    }
    
    private void clear(SharedPreferences prefs) {
    	if (cryptostore.clearStore()) {
    		clearKeyPairAndMaiIdText();
	        Toast.makeText(MainActivity.this, "Deleted stored keys.", Toast.LENGTH_LONG)
	                .show();
    	} else {
    		Toast.makeText(MainActivity.this, "Error deleting stored keys.", Toast.LENGTH_LONG)
            	.show();
    	}
    }
    
    public void onClick_uploadPublicKey(View view) {
        SharedPreferences prefs = PreferenceManager
                .getDefaultSharedPreferences(this);
        uploadPublicKey(prefs);
    }
    
    private void updateServerName() {
    	cryptostore.setServerName(serverNameEdit.getText().toString());
    }
    
    private void uploadPublicKey(final SharedPreferences prefs) {
    	
    	updateServerName();

        new AsyncTask<Void, Void, Boolean>() {
        	
        	Exception error = null;
        	String serverAnswer;
        	
        	@Override
            protected void onPreExecute() {
                Toast.makeText(MainActivity.this, "Uploading public key...",
                        Toast.LENGTH_SHORT).show();
                setProgressBarIndeterminateVisibility(true);
            }
        	

            protected Boolean doInBackground(Void... arg0) {
                try {
                    if (! cryptostore.hasStoredKeyPairAndMaiId()) {
                        throw new IllegalArgumentException(
                                "Public key not found. Generate keys first.");
                    }
                    
                    serverAnswer = cryptostore.uploadPublicKey();
                    return true;
                } catch (Exception e) {
		            Log.e(TAG, "Error uploading public key: " + e.getMessage(), error);
		            error = e;
		
		            return false;
                }
            }
            

            @Override
            protected void onPostExecute(Boolean result) {
                setProgressBarIndeterminateVisibility(false);

                if (result) {
                    Toast.makeText(MainActivity.this,
                            "Successfully uploaded public key: " + serverAnswer,
                            Toast.LENGTH_SHORT).show();
                } else {
                    Toast.makeText(
                            MainActivity.this,
                            error == null ? "Error uploading public key" : error
                                    .getMessage(), Toast.LENGTH_LONG).show();
                }
            }
        }.execute();
    }
    
    public void onClick_uploadSignedData(View view) {
        SharedPreferences prefs = PreferenceManager
                .getDefaultSharedPreferences(this);
        uploadSignedData(prefs);
    }
    
    private void uploadSignedData(final SharedPreferences prefs) {
    	
        updateServerName();
    	final Result result = new Result();
    	result.genResults();
    	
		new AsyncTask<Void, Void, Boolean>() {
        	
        	Exception error = null;
        	String serverAnswer;
        	
        	@Override
            protected void onPreExecute() {
                Toast.makeText(MainActivity.this, "Signing and uploading data...",
                        Toast.LENGTH_SHORT).show();
                setProgressBarIndeterminateVisibility(true);
            }
        	

            protected Boolean doInBackground(Void... arg0) {
                try {
                	if (! cryptostore.hasStoredKeyPairAndMaiId()) {
                        throw new IllegalArgumentException(
                                "Public key not found. Generate keys first.");
                    }

                	String jsonData = gson.toJson(result);
                    serverAnswer = cryptostore.signAndUploadData(appIdEdit.getText().toString(), jsonData);
                    return true;
                } catch (Exception e) {
		            Log.e(TAG, "Error uploading signed data: " + e.getMessage(), error);
		            error = e;
		
		            return false;
                }
            }
            

            @Override
            protected void onPostExecute(Boolean result) {
                setProgressBarIndeterminateVisibility(false);

                if (result) {
                    Toast.makeText(MainActivity.this,
                            "Successfully uploaded signed data: " + serverAnswer,
                            Toast.LENGTH_SHORT).show();
                } else {
                    Toast.makeText(
                            MainActivity.this,
                            error == null ? "Error uploading signed data" : error
                                    .getMessage(), Toast.LENGTH_LONG).show();
                }
            }
        }.execute();
    }
}